require 'find'
require 'backup'
require 'fileutils'

class FileAnalyser

  attr_accessor :ignoring

  #``````````````````
  # constructor
  #``````````````````

  def initialize
    @properties = Hash.new
    @config_file = nil
    @ignoring = []
    @cached_file_sizes = Hash.new
  end
  
  #``````````````````
  # interface
  #``````````````````
  
  def FileAnalyser.path_of(local_dir)
    FileAnalyser.property_of(local_dir,"path")
  end
  
  def FileAnalyser.property_of(local_dir,property_name)
    fa = FileAnalyser.load_local(local_dir)
    fa.property_of property_name
  end
  
  def FileAnalyser.properties_of(local_dir,property_name)
    fa = FileAnalyser.load_local(local_dir)
    fa.properties_of property_name
  end
  
  def load_config(filename)
    initialize
    return false unless File.exists? filename
    
    @config_file = filename
    File.open(@config_file,"r") do |file|
      while (line = file.gets)
        inputs = line.chomp!.split("=")
        next if inputs.length != 2
        put_at inputs[0], inputs[1]
      end
    end
    return true
  end
  
  def add_property(key,value)
    return false if @config_file.nil?
    File.open(@config_file,"a") { |file| file.puts "#{key}=#{value}"}
    put_at key, value 
  end
  
  def property_of(key)
    get_at(key)[0]
  end
  
  def properties_of(key)
    get_at key
  end

  def size_of(file_or_directory)
    return 0 if file_or_directory.nil? or !File.exists?(file_or_directory)
    return @cached_file_sizes[file_or_directory] unless @cached_file_sizes[file_or_directory].nil?
    running_count = 0
    Find.find(file_or_directory) do |path|
      running_count += File.size(path)
    end
    @cached_file_sizes[file_or_directory] = running_count
    running_count
  end

  def directories_in(root_directory)
    return [] unless File.exists?(root_directory)
    all_directories = []
    Find.find(root_directory) do |path|
      next if root_directory == path
      Find.prune if @ignoring.include?(File.basename(path))
      if FileTest.directory?(path)
        all_directories << path
      end
    end
    all_directories
  end
  
  def files_in(directory, is_recursive = true)
    return [] unless File.exists?(directory)
    
    all_files = []
    if is_recursive
      Find.find(directory) do |path|
        should_ignore = @ignoring.include?(File.basename(path))
        Find.prune if should_ignore
        unless FileTest.directory?(path) or should_ignore
          all_files << path
        end
      end
    else
      Dir.foreach( directory ) do |filename|
        full_name = "#{directory}/#{filename}"
        all_files << full_name if File.file?(full_name)
      end
    end
    all_files
  end

  def FileAnalyser.merge(directory,filename)
    "#{fix_absolute_directory(directory)}#{FileAnalyser.file_delimiter_for(directory)}#{fix_relative_file(filename)}"
  end
  
  def FileAnalyser.file_delimiter?(character)
    character == "/" or character == "\\"
  end
  
  def FileAnalyser.file_delimiter_for(directory)
    return "\\" if directory.nil?
    directory.include?("/") ? "/" : "\\"
  end  
  
  def FileAnalyser.fix_absolute_directory(directory)
    last_character = directory[-1..-1]
    if file_delimiter? last_character
      directory = directory[0...-1]
    end
    directory
  end  

  def FileAnalyser.fix_relative_file(file)
    file = fix_absolute_directory(file)
    first_character = file[0..0]
    if file_delimiter? first_character
      file = file[1..-1]
    end
    file
  end

  def FileAnalyser.rename_file_extension(file,new_extension)
    dotIndex = file.index "."
    new_file = dotIndex.nil? ? file : file[0...dotIndex] 
    return "#{new_file}#{new_extension}"
  end
  
  def FileAnalyser.image?(file)
    !(file.downcase =~ /\.jpg|\.gif$/).nil?
  end

    
  #``````````````````
  # private methods
  #``````````````````
  
  private
  
    def get_at key
      return [] if @properties[key].nil?
      return @properties[key]
    end
    
    def put_at key, new_value
      values = get_at key
      values << new_value
      @properties[key] = values
    end
    
    def FileAnalyser.load_local(local_dir)
      config_file = File.directory?(local_dir) ? FileAnalyser.merge(local_dir,".dir") : local_dir
      fa = FileAnalyser.new
      fa.load_config(config_file)
      fa
    end
    
  
end
